#include "StdAfx.h"
#include "myIDirect3DDevice9.h"

SWEGL_DXWRAPPER_IMPLEMENT_IUNKNOWN(myIDirect3DDevice9, IDirect3DDevice9);

myIDirect3DDevice9::myIDirect3DDevice9(myIDirect3D9 *direct3d, HWND hWnd)
{
	SWEGL_DXWRAPPER_INIT_IUNKNOWN();

	m_direct3d = direct3d;
	m_hWnd = hWnd;

	RECT rect;
	GetClientRect(hWnd, &rect);
	int width = rect.right - rect.left;
	int height = rect.bottom - rect.top;
	renderer.openWindow(width, height);

	m_backbufferSurface = new myIDirect3DSurface9(renderer.m_rasterizer.m_colorBuffer);

	HDC hdc = GetDC(m_hWnd);
    hbm = CreateCompatibleBitmap(hdc, width, height);
	ReleaseDC(m_hWnd, hdc);

	binfos.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
	binfos.bmiHeader.biWidth = width;
	binfos.bmiHeader.biHeight = height;
	binfos.bmiHeader.biPlanes = 1;
	binfos.bmiHeader.biBitCount = 32;
	binfos.bmiHeader.biCompression = BI_RGB;
	binfos.bmiHeader.biSizeImage = width * height * 4;
}

myIDirect3DDevice9::~myIDirect3DDevice9()
{
}

HRESULT myIDirect3DDevice9::TestCooperativeLevel()
{
    SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
}

UINT myIDirect3DDevice9::GetAvailableTextureMem()
{
    sweglInfo("%s: NYI\n", SWEGL_FUNCTION); return 0;
}

HRESULT myIDirect3DDevice9::EvictManagedResources()
{
    SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
}

HRESULT myIDirect3DDevice9::GetDirect3D(IDirect3D9** ppD3D9)
{
	m_direct3d->AddRef();
	*ppD3D9 = m_direct3d;
	return S_OK;
}

HRESULT myIDirect3DDevice9::GetDeviceCaps(D3DCAPS9* pCaps)
{
	sweglInfo("%s\n", SWEGL_FUNCTION);

	/* Device Info */
	pCaps->DeviceType = D3DDEVTYPE_SW;
	pCaps->AdapterOrdinal = 0;
	/* Caps from DX7 Draw */
	pCaps->Caps = 0;
	pCaps->Caps2 = 0;
	pCaps->Caps3 = 0;
	pCaps->PresentationIntervals = D3DPRESENT_INTERVAL_IMMEDIATE;

    /* Cursor Caps */
    pCaps->CursorCaps = 0;

    /* 3D Device Caps */
	pCaps->DevCaps = D3DCPCAPS_SOFTWARE;

    pCaps->PrimitiveMiscCaps = D3DPMISCCAPS_MASKZ; // and more
    pCaps->RasterCaps = D3DPRASTERCAPS_ZTEST; // and more
    pCaps->ZCmpCaps = D3DPCMPCAPS_ALWAYS; // and more
    pCaps->SrcBlendCaps = 0;
    pCaps->DestBlendCaps = 0;
    pCaps->AlphaCmpCaps = 0;
    pCaps->ShadeCaps = 0;
    pCaps->TextureCaps = D3DPTEXTURECAPS_ALPHA | D3DPTEXTURECAPS_MIPMAP | D3DPTEXTURECAPS_PERSPECTIVE | D3DPTEXTURECAPS_NONPOW2CONDITIONAL;
    pCaps->TextureFilterCaps = ~0;          // D3DPTFILTERCAPS for IDirect3DTexture9's
    pCaps->CubeTextureFilterCaps = ~0;      // D3DPTFILTERCAPS for IDirect3DCubeTexture9's
    pCaps->VolumeTextureFilterCaps = ~0;    // D3DPTFILTERCAPS for IDirect3DVolumeTexture9's
    pCaps->TextureAddressCaps = ~0;         // D3DPTADDRESSCAPS for IDirect3DTexture9's
    pCaps->VolumeTextureAddressCaps = ~0;   // D3DPTADDRESSCAPS for IDirect3DVolumeTexture9's

    pCaps->LineCaps = 0;                   // D3DLINECAPS

    pCaps->MaxTextureWidth = 4096;
	pCaps->MaxTextureHeight = 4096;
    pCaps->MaxVolumeExtent = 0;

    pCaps->MaxTextureRepeat = 128;
    pCaps->MaxTextureAspectRatio = 128;
    pCaps->MaxAnisotropy = 0;
    pCaps->MaxVertexW = 0;

    pCaps->GuardBandLeft = 0;
    pCaps->GuardBandTop = 0;
    pCaps->GuardBandRight = 0;
    pCaps->GuardBandBottom = 0;

    pCaps->ExtentsAdjust = 0;
    pCaps->StencilCaps = 0;

    pCaps->FVFCaps = 0; // todo
    pCaps->TextureOpCaps = ~0;
    pCaps->MaxTextureBlendStages = 8;
    pCaps->MaxSimultaneousTextures = 8;

    pCaps->VertexProcessingCaps = 0;
    pCaps->MaxActiveLights = 0;
    pCaps->MaxUserClipPlanes = 0;
    pCaps->MaxVertexBlendMatrices = 0;
    pCaps->MaxVertexBlendMatrixIndex = 0;

    pCaps->MaxPointSize = 0;

    pCaps->MaxPrimitiveCount = 1024 * 1024;          // max number of primitives per DrawPrimitive call
    pCaps->MaxVertexIndex = 1024 * 1024;
    pCaps->MaxStreams = 16;
    pCaps->MaxStreamStride = 256;            // max stride for SetStreamSource

    pCaps->VertexShaderVersion = 0;
    pCaps->MaxVertexShaderConst = 0;       // number of vertex shader constant registers

    pCaps->PixelShaderVersion = 0;
    pCaps->PixelShader1xMaxValue = 0;      // max value storable in registers of ps.1.x shaders

    // Here are the DX9 specific ones
    pCaps->DevCaps2 = 0;

    pCaps->MaxNpatchTessellationLevel = 0;
    pCaps->Reserved5 = 0;

    pCaps->MasterAdapterOrdinal = 0;       // ordinal of master adaptor for adapter group
    pCaps->AdapterOrdinalInGroup = 0;      // ordinal inside the adapter group
    pCaps->NumberOfAdaptersInGroup = 1;    // number of adapters in this adapter group (only if master)
    pCaps->DeclTypes = ~0;                  // Data types, supported in vertex declarations
    pCaps->NumSimultaneousRTs = 1;         // Will be at least 1
    pCaps->StretchRectFilterCaps = 0;      // Filter caps supported by StretchRect
    //pCaps->VS20Caps;
    //pCaps->PS20Caps;
    pCaps->VertexTextureFilterCaps = ~0;    // D3DPTFILTERCAPS for IDirect3DTexture9's for texture, used in vertex shaders
    pCaps->MaxVShaderInstructionsExecuted = 0; // maximum number of vertex shader instructions that can be executed
    pCaps->MaxPShaderInstructionsExecuted = 0; // maximum number of pixel shader instructions that can be executed
    pCaps->MaxVertexShader30InstructionSlots = 0; 
    pCaps->MaxPixelShader30InstructionSlots = 0;

	return S_OK;
}

HRESULT myIDirect3DDevice9::GetDisplayMode(UINT iSwapChain,D3DDISPLAYMODE* pMode)
{
    sweglInfo("%s: %d\n", SWEGL_FUNCTION, iSwapChain);
	pMode->Width = renderer.m_rasterizer.m_colorBuffer->width();
	pMode->Height = renderer.m_rasterizer.m_colorBuffer->height();
	pMode->RefreshRate = 60;
	pMode->Format = D3DFMT_X8R8G8B8;
	return S_OK;
}

HRESULT myIDirect3DDevice9::GetCreationParameters(D3DDEVICE_CREATION_PARAMETERS *pParameters)
{
    SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
}

HRESULT myIDirect3DDevice9::SetCursorProperties(UINT XHotSpot,UINT YHotSpot,IDirect3DSurface9* pCursorBitmap)
{
    SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
}

void myIDirect3DDevice9::SetCursorPosition(int X,int Y,DWORD Flags)
{
    sweglInfo("%s: NYI\n", SWEGL_FUNCTION); 
}

BOOL myIDirect3DDevice9::ShowCursor(BOOL bShow)
{
    SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
}

HRESULT myIDirect3DDevice9::CreateAdditionalSwapChain(D3DPRESENT_PARAMETERS* pPresentationParameters,IDirect3DSwapChain9** pSwapChain)  
{
    SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
}

HRESULT myIDirect3DDevice9::GetSwapChain(UINT iSwapChain,IDirect3DSwapChain9** pSwapChain)
{
    SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
}

UINT myIDirect3DDevice9::GetNumberOfSwapChains()
{
   sweglInfo("%s: NYI\n", SWEGL_FUNCTION);  return 0;
}

HRESULT myIDirect3DDevice9::Reset(D3DPRESENT_PARAMETERS* pPresentationParameters)
{
    SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
}

HRESULT myIDirect3DDevice9::Present(CONST RECT* pSourceRect,CONST RECT* pDestRect,HWND hDestWindowOverride,CONST RGNDATA* pDirtyRegion)
{
	PAINTSTRUCT ps; 

	InvalidateRect(m_hWnd, NULL, 1);
	HDC hdc = BeginPaint(m_hWnd, &ps);
    HDC render_hdc = CreateCompatibleDC(hdc);

    SelectObject(render_hdc, hbm);
	SetDIBits(render_hdc, hbm, 0, binfos.bmiHeader.biHeight, renderer.m_rasterizer.m_colorBuffer->data(), &binfos, DIB_RGB_COLORS);
	BitBlt(hdc, 0, 0, binfos.bmiHeader.biWidth, binfos.bmiHeader.biHeight, render_hdc, 0, 0, SRCCOPY);
    EndPaint(m_hWnd, &ps); 

	DeleteDC (render_hdc);

	return S_OK;
}

HRESULT myIDirect3DDevice9::GetBackBuffer(UINT iSwapChain,UINT iBackBuffer,D3DBACKBUFFER_TYPE Type,IDirect3DSurface9** ppBackBuffer)
{
    sweglInfo("%s: %d %d\n", SWEGL_FUNCTION, iSwapChain, iBackBuffer);
	*ppBackBuffer = m_backbufferSurface;
	return S_OK;
}

HRESULT myIDirect3DDevice9::GetRasterStatus(UINT iSwapChain,D3DRASTER_STATUS* pRasterStatus)
{
    SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
}

HRESULT myIDirect3DDevice9::SetDialogBoxMode(BOOL bEnableDialogs)
{
    SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
}

void myIDirect3DDevice9::SetGammaRamp(UINT iSwapChain,DWORD Flags,CONST D3DGAMMARAMP* pRamp)
{
	sweglInfo("%s: NYI\n", SWEGL_FUNCTION); 
}

void myIDirect3DDevice9::GetGammaRamp(UINT iSwapChain,D3DGAMMARAMP* pRamp)
{
	sweglInfo("%s: NYI\n", SWEGL_FUNCTION); 
}

HRESULT myIDirect3DDevice9::CreateTexture(UINT Width,UINT Height,UINT Levels,DWORD Usage,D3DFORMAT Format,D3DPOOL Pool,IDirect3DTexture9** ppTexture,HANDLE* pSharedHandle)
{
	sweglInfo("%s: %dx%dx%d\n", SWEGL_FUNCTION, Width, Height, Levels);
	Texture *tex = new Texture(Width, Height, Levels);
	*ppTexture = new myIDirect3DTexture9(tex);
    return S_OK;
}

HRESULT myIDirect3DDevice9::CreateVolumeTexture(UINT Width,UINT Height,UINT Depth,UINT Levels,DWORD Usage,D3DFORMAT Format,D3DPOOL Pool,IDirect3DVolumeTexture9** ppVolumeTexture,HANDLE* pSharedHandle)
{
    SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
}

HRESULT myIDirect3DDevice9::CreateCubeTexture(UINT EdgeLength,UINT Levels,DWORD Usage,D3DFORMAT Format,D3DPOOL Pool,IDirect3DCubeTexture9** ppCubeTexture,HANDLE* pSharedHandle)
{
   SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
}

HRESULT myIDirect3DDevice9::CreateVertexBuffer(UINT Length,DWORD Usage,DWORD FVF,D3DPOOL Pool,IDirect3DVertexBuffer9** ppVertexBuffer,HANDLE* pSharedHandle)
{
	VertexBuffer *vb = renderer.createVertexBuffer(Length);
	*ppVertexBuffer = new myIDirect3DVertexBuffer9(vb);
    return S_OK;
}

HRESULT myIDirect3DDevice9::CreateIndexBuffer(UINT Length,DWORD Usage,D3DFORMAT Format,D3DPOOL Pool,IDirect3DIndexBuffer9** ppIndexBuffer,HANDLE* pSharedHandle)
{
	IndexBuffer::IndexType indexType = Format == D3DFMT_INDEX16 ? IndexBuffer::Index16Bit : IndexBuffer::Index32Bit;
	Length /= Format == D3DFMT_INDEX16 ? 2 : 4;
	IndexBuffer *ib = renderer.createIndexBuffer(indexType, Length);
	*ppIndexBuffer = new myIDirect3DIndexBuffer9(ib);
    return S_OK;
}

HRESULT myIDirect3DDevice9::CreateRenderTarget(UINT Width,UINT Height,D3DFORMAT Format,D3DMULTISAMPLE_TYPE MultiSample,DWORD MultisampleQuality,BOOL Lockable,IDirect3DSurface9** ppSurface,HANDLE* pSharedHandle)
{
    SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
}

HRESULT myIDirect3DDevice9::CreateDepthStencilSurface(UINT Width,UINT Height,D3DFORMAT Format,D3DMULTISAMPLE_TYPE MultiSample,DWORD MultisampleQuality,BOOL Discard,IDirect3DSurface9** ppSurface,HANDLE* pSharedHandle)
{
    SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
}

HRESULT myIDirect3DDevice9::UpdateSurface(IDirect3DSurface9* pSourceSurface,CONST RECT* pSourceRect,IDirect3DSurface9* pDestinationSurface,CONST POINT* pDestPoint)
{
    SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
}

HRESULT myIDirect3DDevice9::UpdateTexture(IDirect3DBaseTexture9* pSourceTexture,IDirect3DBaseTexture9* pDestinationTexture)
{
    SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
}

HRESULT myIDirect3DDevice9::GetRenderTargetData(IDirect3DSurface9* pRenderTarget,IDirect3DSurface9* pDestSurface)
{
    SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
}

HRESULT myIDirect3DDevice9::GetFrontBufferData(UINT iSwapChain,IDirect3DSurface9* pDestSurface)
{
   SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
}

HRESULT myIDirect3DDevice9::StretchRect(IDirect3DSurface9* pSourceSurface,CONST RECT* pSourceRect,IDirect3DSurface9* pDestSurface,CONST RECT* pDestRect,D3DTEXTUREFILTERTYPE Filter)
{
    SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
}

HRESULT myIDirect3DDevice9::ColorFill(IDirect3DSurface9* pSurface,CONST RECT* pRect,D3DCOLOR color)
{
    SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
}

HRESULT myIDirect3DDevice9::CreateOffscreenPlainSurface(UINT Width,UINT Height,D3DFORMAT Format,D3DPOOL Pool,IDirect3DSurface9** ppSurface,HANDLE* pSharedHandle)
{
    SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
}

HRESULT myIDirect3DDevice9::SetRenderTarget(DWORD RenderTargetIndex,IDirect3DSurface9* pRenderTarget)
{
    SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
}

HRESULT myIDirect3DDevice9::GetRenderTarget(DWORD RenderTargetIndex,IDirect3DSurface9** ppRenderTarget)
{
    SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
}

HRESULT myIDirect3DDevice9::SetDepthStencilSurface(IDirect3DSurface9* pNewZStencil)
{
    SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
}

HRESULT myIDirect3DDevice9::GetDepthStencilSurface(IDirect3DSurface9** ppZStencilSurface)
{
    SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
}

HRESULT myIDirect3DDevice9::BeginScene()
{
	// nothing to do
	return S_OK;
}

HRESULT myIDirect3DDevice9::EndScene()
{
	// nothing to do
	return S_OK;
}

HRESULT myIDirect3DDevice9::Clear(DWORD Count,CONST D3DRECT* pRects,DWORD Flags,D3DCOLOR Color,float Z,DWORD Stencil)
{
	uint sweglFlags = 0;
	sweglFlags |= Flags & D3DCLEAR_TARGET ? ClearFlags::Target : 0;
	sweglFlags |= Flags & D3DCLEAR_ZBUFFER ? ClearFlags::ZBuffer : 0;
	sweglFlags |= Flags & D3DCLEAR_STENCIL ? ClearFlags::Stencil : 0;
	renderer.clear(sweglFlags, Color);
    return S_OK;
}

HRESULT myIDirect3DDevice9::SetTransform(D3DTRANSFORMSTATETYPE State,CONST D3DMATRIX* pMatrix)
{
	if (State == D3DTS_WORLD)
		renderer.setWorldMatrix(Matrix4x4(reinterpret_cast<const float *>(pMatrix->m)));
	else if (State == D3DTS_VIEW)
		renderer.setViewMatrix(Matrix4x4(reinterpret_cast<const float *>(pMatrix->m)));
	else if (State == D3DTS_PROJECTION)
		renderer.setProjectionMatrix(Matrix4x4(reinterpret_cast<const float *>(pMatrix->m)));
    return S_OK;
}

HRESULT myIDirect3DDevice9::GetTransform(D3DTRANSFORMSTATETYPE State,D3DMATRIX* pMatrix)
{
    SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
}

HRESULT myIDirect3DDevice9::MultiplyTransform(D3DTRANSFORMSTATETYPE State,CONST D3DMATRIX* pMatrix)
{
   SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
}

HRESULT myIDirect3DDevice9::SetViewport(CONST D3DVIEWPORT9* pViewport)
{
	sweglInfo("%s: %u %u - %u %u\n", SWEGL_FUNCTION, pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height);
	renderer.setViewport(Viewport(pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height));
	return S_OK;
}

HRESULT myIDirect3DDevice9::GetViewport(D3DVIEWPORT9* pViewport)
{
	sweglInfo("%s\n", SWEGL_FUNCTION); 
	pViewport->X = renderer.m_viewport.x;
	pViewport->Y = renderer.m_viewport.y;
	pViewport->Width = renderer.m_viewport.width;
	pViewport->Height = renderer.m_viewport.height;
	return S_OK;
}

HRESULT myIDirect3DDevice9::SetMaterial(CONST D3DMATERIAL9* pMaterial)
{
    SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
}

HRESULT myIDirect3DDevice9::GetMaterial(D3DMATERIAL9* pMaterial)
{
    SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
}

HRESULT myIDirect3DDevice9::SetLight(DWORD Index,CONST D3DLIGHT9* pLight)
{
    SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
}

HRESULT myIDirect3DDevice9::GetLight(DWORD Index,D3DLIGHT9* pLight)
{
    SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
}

HRESULT myIDirect3DDevice9::LightEnable(DWORD Index,BOOL Enable)
{
    SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
}

HRESULT myIDirect3DDevice9::GetLightEnable(DWORD Index,BOOL* pEnable)
{
    SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
}

HRESULT myIDirect3DDevice9::SetClipPlane(DWORD Index,CONST float* pPlane)
{
    SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
}

HRESULT myIDirect3DDevice9::GetClipPlane(DWORD Index,float* pPlane)
{
    SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
}

HRESULT myIDirect3DDevice9::SetRenderState(D3DRENDERSTATETYPE State,DWORD Value)
{
    SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
}

HRESULT myIDirect3DDevice9::GetRenderState(D3DRENDERSTATETYPE State,DWORD* pValue)
{
    SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
}

HRESULT myIDirect3DDevice9::CreateStateBlock(D3DSTATEBLOCKTYPE Type,IDirect3DStateBlock9** ppSB)
{
    SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
}

HRESULT myIDirect3DDevice9::BeginStateBlock()
{
    SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
}

HRESULT myIDirect3DDevice9::EndStateBlock(IDirect3DStateBlock9** ppSB)
{
    SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
}

HRESULT myIDirect3DDevice9::SetClipStatus(CONST D3DCLIPSTATUS9* pClipStatus)
{
    SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
}

HRESULT myIDirect3DDevice9::GetClipStatus(D3DCLIPSTATUS9* pClipStatus)
{
    SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
}

HRESULT myIDirect3DDevice9::GetTexture(DWORD Stage,IDirect3DBaseTexture9** ppTexture)
{
    SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
}

HRESULT myIDirect3DDevice9::SetTexture(DWORD Stage,IDirect3DBaseTexture9* pTexture)
{
	myIDirect3DTexture9 *tex = static_cast<myIDirect3DTexture9 *>(pTexture);
	renderer.setTexture(Stage, tex ? tex->m_tex : 0);
	return S_OK;
}

HRESULT myIDirect3DDevice9::GetTextureStageState(DWORD Stage,D3DTEXTURESTAGESTATETYPE Type,DWORD* pValue)
{
    SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
}



HRESULT myIDirect3DDevice9::SetTextureStageState(DWORD Stage,D3DTEXTURESTAGESTATETYPE Type,DWORD Value)
{
	static TextureStage::Argument ColorArgConv[] = {
		TextureStage::Diffuse,
		TextureStage::Current,
		TextureStage::Texture,
		TextureStage::TextureFactor,
		TextureStage::Specular,
		TextureStage::Temp,
		TextureStage::Constant,
	};

	sweglAssert(Stage < 8);
	if (Type == D3DTSS_COLOROP)
	{
		static TextureStage::Operation conv[] = {
			TextureStage::Disabled,
			TextureStage::Disabled,
			TextureStage::Disabled,
			TextureStage::Disabled,
			TextureStage::Modulate,
			TextureStage::Modulate2X,
			TextureStage::Modulate4X,
			TextureStage::Add, 
			TextureStage::AddSigned, 
			TextureStage::AddSigned2X, 
			TextureStage::Substract, 
			TextureStage::AddSmooth,
		};
		sweglAssert(Value <= sizeof(conv) / sizeof(conv[0]));
		renderer.textureStage(Stage)->m_colorOp = conv[Value];
	}
	else if (Type == D3DTSS_COLORARG1)
	{
		sweglAssert(Value <= sizeof(ColorArgConv) / sizeof(ColorArgConv[0]));
		renderer.textureStage(Stage)->m_colorArg1 = ColorArgConv[Value];
	}
	else if (Type == D3DTSS_COLORARG2)
	{
		sweglAssert(Value <= sizeof(ColorArgConv) / sizeof(ColorArgConv[0]));
		renderer.textureStage(Stage)->m_colorArg2 = ColorArgConv[Value];
	}
	else if (Type == D3DTSS_TEXCOORDINDEX)
	{
		sweglAssert(Value < 8);
		renderer.textureStage(Stage)->texCoordIndex = Value;
	}
	else
	{
		SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
	}
	return S_OK;
}

HRESULT myIDirect3DDevice9::GetSamplerState(DWORD Sampler,D3DSAMPLERSTATETYPE Type,DWORD* pValue)
{
    SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
}

HRESULT myIDirect3DDevice9::SetSamplerState(DWORD Sampler,D3DSAMPLERSTATETYPE Type,DWORD Value)
{
    SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
}

HRESULT myIDirect3DDevice9::ValidateDevice(DWORD* pNumPasses)
{
    SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
}

HRESULT myIDirect3DDevice9::SetPaletteEntries(UINT PaletteNumber,CONST PALETTEENTRY* pEntries)
{
    SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
}

HRESULT myIDirect3DDevice9::GetPaletteEntries(UINT PaletteNumber,PALETTEENTRY* pEntries)
{
   SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
}

HRESULT myIDirect3DDevice9::SetCurrentTexturePalette(UINT PaletteNumber)
{
    SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
}

HRESULT myIDirect3DDevice9::GetCurrentTexturePalette(UINT *PaletteNumber)
{
    SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
}

HRESULT myIDirect3DDevice9::SetScissorRect(CONST RECT* pRect)
{
    SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
}

HRESULT myIDirect3DDevice9::GetScissorRect( RECT* pRect)
{
    SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
}

HRESULT myIDirect3DDevice9::SetSoftwareVertexProcessing(BOOL bSoftware)
{
    SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
}

BOOL    myIDirect3DDevice9::GetSoftwareVertexProcessing()
{
    SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
}

HRESULT myIDirect3DDevice9::SetNPatchMode(float nSegments)
{
    SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
}

float myIDirect3DDevice9::GetNPatchMode()
{
	sweglInfo("%s: NYI\n", SWEGL_FUNCTION); 
   return 0;
}

HRESULT myIDirect3DDevice9::DrawPrimitive(D3DPRIMITIVETYPE PrimitiveType,UINT StartVertex,UINT PrimitiveCount)
{
	if (PrimitiveType == D3DPT_TRIANGLESTRIP)
		renderer.draw(swegl::Primitive::TRIANGLE_STRIP, PrimitiveCount, StartVertex);
	else if (PrimitiveType == D3DPT_TRIANGLELIST)
		renderer.draw(swegl::Primitive::TRIANGLE_LIST, PrimitiveCount, StartVertex);
	else
		sweglAssert("NYI\n");
	SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
}

HRESULT myIDirect3DDevice9::DrawIndexedPrimitive(D3DPRIMITIVETYPE PrimitiveType,INT BaseVertexIndex,UINT MinVertexIndex,UINT NumVertices,UINT startIndex,UINT primCount)
{
	renderer.drawIndexed(swegl::Primitive::TRIANGLE_LIST, primCount, startIndex);
    SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
}

HRESULT myIDirect3DDevice9::DrawPrimitiveUP(D3DPRIMITIVETYPE PrimitiveType,UINT PrimitiveCount,CONST void* pVertexStreamZeroData,UINT VertexStreamZeroStride)
{
   SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
}

HRESULT myIDirect3DDevice9::DrawIndexedPrimitiveUP(D3DPRIMITIVETYPE PrimitiveType,UINT MinVertexIndex,UINT NumVertices,UINT PrimitiveCount,CONST void* pIndexData,D3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,UINT VertexStreamZeroStride)
{
    SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
}

HRESULT myIDirect3DDevice9::ProcessVertices(UINT SrcStartIndex,UINT DestIndex,UINT VertexCount,IDirect3DVertexBuffer9* pDestBuffer,IDirect3DVertexDeclaration9* pVertexDecl,DWORD Flags)
{
SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
}

HRESULT myIDirect3DDevice9::CreateVertexDeclaration(CONST D3DVERTEXELEMENT9* pVertexElements,IDirect3DVertexDeclaration9** ppDecl)
{
    SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
}

HRESULT myIDirect3DDevice9::SetVertexDeclaration(IDirect3DVertexDeclaration9* pDecl)
{
    SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
}

HRESULT myIDirect3DDevice9::GetVertexDeclaration(IDirect3DVertexDeclaration9** ppDecl)
{
    SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
}

HRESULT myIDirect3DDevice9::SetFVF(DWORD FVF)
{
	InputVertexFormat vertexFormat;
	sweglAssert(FVF & D3DFVF_XYZ); // currently, position is always needed!
	sint currentOffset = 0;
	if (FVF & D3DFVF_XYZ)
	{
		vertexFormat.positionOffset = currentOffset;
		currentOffset += 3 * sizeof(float);
	}
	if (FVF & D3DFVF_DIFFUSE)
	{
		vertexFormat.diffuseOffset = currentOffset;
		currentOffset += sizeof(uint32);
	}
	if (FVF & D3DFVF_SPECULAR)
	{
		vertexFormat.specularOffset = currentOffset;
		currentOffset += sizeof(uint32);
	}
	if ((FVF & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT)
	{
		vertexFormat.textureOffset = currentOffset;
		vertexFormat.numTextureCoords = (FVF & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT;
	}
	vertexFormat.vertexSize = currentOffset + vertexFormat.numTextureCoords * 2 * sizeof(float);
	renderer.setVertexFormat(vertexFormat);
    return S_OK;
}

HRESULT myIDirect3DDevice9::GetFVF(DWORD* pFVF)
{
   SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
}

HRESULT myIDirect3DDevice9::CreateVertexShader(CONST DWORD* pFunction,IDirect3DVertexShader9** ppShader)
{
    SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
}

HRESULT myIDirect3DDevice9::SetVertexShader(IDirect3DVertexShader9* pShader)
{
    SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
}

HRESULT myIDirect3DDevice9::GetVertexShader(IDirect3DVertexShader9** ppShader)
{
   SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
}

HRESULT myIDirect3DDevice9::SetVertexShaderConstantF(UINT StartRegister,CONST float* pConstantData,UINT Vector4fCount)
{
    SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
}

HRESULT myIDirect3DDevice9::GetVertexShaderConstantF(UINT StartRegister,float* pConstantData,UINT Vector4fCount)
{
    SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
}

HRESULT myIDirect3DDevice9::SetVertexShaderConstantI(UINT StartRegister,CONST int* pConstantData,UINT Vector4iCount)
{
   SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
}

HRESULT myIDirect3DDevice9::GetVertexShaderConstantI(UINT StartRegister,int* pConstantData,UINT Vector4iCount)
{
   SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
}

HRESULT myIDirect3DDevice9::SetVertexShaderConstantB(UINT StartRegister,CONST BOOL* pConstantData,UINT  BoolCount)
{
    SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
}

HRESULT myIDirect3DDevice9::GetVertexShaderConstantB(UINT StartRegister,BOOL* pConstantData,UINT BoolCount)
{
   SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
}

HRESULT myIDirect3DDevice9::SetStreamSource(UINT StreamNumber,IDirect3DVertexBuffer9* pStreamData,UINT OffsetInBytes,UINT Stride)
{
	sweglAssert(StreamNumber == 0);
	myIDirect3DVertexBuffer9 *vb = static_cast<myIDirect3DVertexBuffer9 *>(pStreamData);
	renderer.setVertexBuffer(vb->m_vb);
    return S_OK;
}

HRESULT myIDirect3DDevice9::GetStreamSource(UINT StreamNumber,IDirect3DVertexBuffer9** ppStreamData,UINT* OffsetInBytes,UINT* pStride)
{
    SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
}

HRESULT myIDirect3DDevice9::SetStreamSourceFreq(UINT StreamNumber,UINT Divider)
{
    SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
}

HRESULT myIDirect3DDevice9::GetStreamSourceFreq(UINT StreamNumber,UINT* Divider)
{
    SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
}

HRESULT myIDirect3DDevice9::SetIndices(IDirect3DIndexBuffer9* pIndexData)
{
	myIDirect3DIndexBuffer9 *ib = static_cast<myIDirect3DIndexBuffer9 *>(pIndexData);
	renderer.setIndexBuffer(ib->m_ib);
    return S_OK;
}

HRESULT myIDirect3DDevice9::GetIndices(IDirect3DIndexBuffer9** ppIndexData)
{
    SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
}

HRESULT myIDirect3DDevice9::CreatePixelShader(CONST DWORD* pFunction,IDirect3DPixelShader9** ppShader)
{
    SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
}

HRESULT myIDirect3DDevice9::SetPixelShader(IDirect3DPixelShader9* pShader)
{
    SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
}

HRESULT myIDirect3DDevice9::GetPixelShader(IDirect3DPixelShader9** ppShader)
{
   SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
}

HRESULT myIDirect3DDevice9::SetPixelShaderConstantF(UINT StartRegister,CONST float* pConstantData,UINT Vector4fCount)
{
    SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
}

HRESULT myIDirect3DDevice9::GetPixelShaderConstantF(UINT StartRegister,float* pConstantData,UINT Vector4fCount)
{
    SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
}

HRESULT myIDirect3DDevice9::SetPixelShaderConstantI(UINT StartRegister,CONST int* pConstantData,UINT Vector4iCount)
{
    SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
}

HRESULT myIDirect3DDevice9::GetPixelShaderConstantI(UINT StartRegister,int* pConstantData,UINT Vector4iCount)
{
   SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
}

HRESULT myIDirect3DDevice9::SetPixelShaderConstantB(UINT StartRegister,CONST BOOL* pConstantData,UINT  BoolCount)
{
    SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
}

HRESULT myIDirect3DDevice9::GetPixelShaderConstantB(UINT StartRegister,BOOL* pConstantData,UINT BoolCount)
{
    SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
}

HRESULT myIDirect3DDevice9::DrawRectPatch(UINT Handle,CONST float* pNumSegs,CONST D3DRECTPATCH_INFO* pRectPatchInfo)
{
    SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
}

HRESULT myIDirect3DDevice9::DrawTriPatch(UINT Handle,CONST float* pNumSegs,CONST D3DTRIPATCH_INFO* pTriPatchInfo)
{
    SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
}

HRESULT myIDirect3DDevice9::DeletePatch(UINT Handle)
{
    SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
}

HRESULT myIDirect3DDevice9::CreateQuery(D3DQUERYTYPE Type,IDirect3DQuery9** ppQuery)
{
    SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
}

/* IDirect3DDevice9Ex methods */
HRESULT myIDirect3DDevice9::SetConvolutionMonoKernel(UINT width, UINT height, float *rows, float *columns)
{
    SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
}
HRESULT myIDirect3DDevice9::ComposeRects(IDirect3DSurface9 *src_surface, IDirect3DSurface9 *dst_surface,
        IDirect3DVertexBuffer9 *src_descs, UINT rect_count, IDirect3DVertexBuffer9 *dst_descs,
        D3DCOMPOSERECTSOP operation, INT offset_x, INT offset_y)
{
    SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
}
HRESULT myIDirect3DDevice9::PresentEx(CONST RECT *pSourceRect, CONST RECT *pDestRect, HWND hDestWindowOverride, CONST RGNDATA *pDirtyRegion, DWORD dwFlags)
{
    SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
}
HRESULT myIDirect3DDevice9::GetGPUThreadPriority(INT *pPriority)
{
    SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
}
HRESULT myIDirect3DDevice9::SetGPUThreadPriority(INT Priority)
{
    SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
}
HRESULT myIDirect3DDevice9::WaitForVBlank(UINT iSwapChain)
{
    SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
}
HRESULT myIDirect3DDevice9::CheckResourceResidency(IDirect3DResource9 **resources, UINT32 resource_count)
{
    SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
}
HRESULT myIDirect3DDevice9::SetMaximumFrameLatency(UINT MaxLatency)
{
    SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
}
HRESULT myIDirect3DDevice9::GetMaximumFrameLatency(UINT *pMaxLatenxy)
{
    SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
}
HRESULT myIDirect3DDevice9::CheckDeviceState(HWND dst_window)
{
    SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
}
HRESULT myIDirect3DDevice9::CreateRenderTargetEx(UINT Width, UINT Height, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, DWORD MultiSampleQuality, BOOL Lockable, IDirect3DSurface9 ** ppSurface, HANDLE *pSharedHandle, DWORD Usage)
{
    SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
}
HRESULT myIDirect3DDevice9::CreateOffscreenPlainSurfaceEx(UINT Width, UINT Height, D3DFORMAT Format, D3DPOOL Pool, IDirect3DSurface9 **ppSurface, HANDLE *pSharedHandle, DWORD Usage)
{
    SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
}
HRESULT myIDirect3DDevice9::CreateDepthStencilSurfaceEx(UINT width, UINT height, D3DFORMAT format,
        D3DMULTISAMPLE_TYPE multisample_type, DWORD multisample_quality, BOOL discard,
        IDirect3DSurface9 **surface, HANDLE *shared_handle, DWORD usage)
{
    SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
}
HRESULT myIDirect3DDevice9::ResetEx(D3DPRESENT_PARAMETERS *pPresentationParameters, D3DDISPLAYMODEEX *pFullscreenDisplayMode)
{
    SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
}
HRESULT myIDirect3DDevice9::GetDisplayModeEx(UINT iSwapChain, D3DDISPLAYMODEEX *pMode, D3DDISPLAYROTATION *pRotation)
{
    SWEGL_DXWRAPPER_NYI(); return E_NOTIMPL;
}
